<?php

defined('SYSPATH') or die('Access error!');
/**
 * 性能分析器
 */
class Profiler {

	public static $rollover = 1000;

        /* 存放要统计的操作 */
	protected static $_marks = array();

	/**
	 *  启动分析器
	 *
	 * $token = Profiler::start('test', 'profiler');
	 *
	 * @param   string  group name
	 * @param   string  benchmark name
	 * @return  string
	 */
	public static function start($group, $name)
	{
		static $counter = 0;

		// 创建唯一的key  base_convert() 函数在任意进制之间转换数字。
		$token = 'kp/'.base_convert($counter++, 10, 32);

		Profiler::$_marks[$token] = array
		(
			'group' => strtolower($group),
			'name'  => (string) $name,

			// 当前mark启动的时间和内存
			'start_time'   => microtime(TRUE),
			'start_memory' => memory_get_usage(),

			// 初始化结束的时间和内存占有
			'stop_time'    => FALSE,
			'stop_memory'  => FALSE,
		);

		return $token;
	}

	/**
	 *  设置结束时的时间和内存占有
	 *
	 * Profiler::stop($token);
	 *
	 * @param   string  token
	 * @return  void
	 */
	public static function stop($token)
	{
		Profiler::$_marks[$token]['stop_time']   = microtime(TRUE);
		Profiler::$_marks[$token]['stop_memory'] = memory_get_usage();
	}

	/**
	 *  删除一个mark
	 * @param   string  token
	 * @return  void
	 */
	public static function delete($token)
	{
		unset(Profiler::$_marks[$token]);
	}

	/**
	 * 返回所有的记录
	 *
	 *     $groups = Profiler::groups();
	 *
	 * @return  array
	 */
	public static function groups()
	{
		$groups = array();

		foreach (Profiler::$_marks as $token => $mark)
		{
			$groups[$mark['group']][$mark['name']][] = $token;
		}

		return $groups;
	}

	/**
	 * 得到 某些操作的 min, max, average and total 记录.
	 *
	 *     $stats = Profiler::stats($tokens);
	 *
	 * @param   array  profiler tokens
	 * @return  array  min, max, average, total
	 * @uses    Profiler::total
	 */
	public static function stats(array $tokens)
	{
		$min = $max = array(
			'time' => NULL,
			'memory' => NULL);

		$total = array(
			'time' => 0,
			'memory' => 0);

		foreach ($tokens as $token)
		{
			list($time, $memory) = Profiler::total($token);

			if ($max['time'] === NULL OR $time > $max['time'])
			{
				$max['time'] = $time;
			}

			if ($min['time'] === NULL OR $time < $min['time'])
			{
				$min['time'] = $time;
			}

			$total['time'] += $time;

			if ($max['memory'] === NULL OR $memory > $max['memory'])
			{
				$max['memory'] = $memory;
			}

			if ($min['memory'] === NULL OR $memory < $min['memory'])
			{
				$min['memory'] = $memory;
			}

			$total['memory'] += $memory;
		}

		$count = count($tokens);

		$average = array(
			'time' => $total['time'] / $count,
			'memory' => $total['memory'] / $count);

		return array(
			'min' => $min,
			'max' => $max,
			'total' => $total,
			'average' => $average);
	}

	/**
	 * 某些操作同一组的 min, max, average and total 记录.
	 *
	 *     $stats = Profiler::group_stats('test');
	 *
	 * @param   mixed  single group name string, or array with group names; all groups by default
	 * @return  array  min, max, average, total
	 */
	public static function group_stats($groups = NULL)
	{
		$groups = ($groups === NULL)
			? Profiler::groups()
			: array_intersect_key(Profiler::groups(), array_flip( (array) $groups));

		$stats = array();

		foreach ($groups as $group => $names)
		{
			foreach ($names as $name => $tokens)
			{
				$_stats = Profiler::stats($tokens);
				$stats[$group][$name] = $_stats['total'];
			}
		}
		$groups = array();

		foreach ($stats as $group => $names)
		{
			$groups[$group]['min'] = $groups[$group]['max'] = array(
				'time' => NULL,
				'memory' => NULL);

			$groups[$group]['total'] = array(
				'time' => 0,
				'memory' => 0);

			foreach ($names as $total)
			{
				if ( ! isset($groups[$group]['min']['time']) OR $groups[$group]['min']['time'] > $total['time'])
				{
					$groups[$group]['min']['time'] = $total['time'];
				}
				if ( ! isset($groups[$group]['min']['memory']) OR $groups[$group]['min']['memory'] > $total['memory'])
				{
					$groups[$group]['min']['memory'] = $total['memory'];
				}

				if ( ! isset($groups[$group]['max']['time']) OR $groups[$group]['max']['time'] < $total['time'])
				{
					$groups[$group]['max']['time'] = $total['time'];
				}
				if ( ! isset($groups[$group]['max']['memory']) OR $groups[$group]['max']['memory'] < $total['memory'])
				{
					$groups[$group]['max']['memory'] = $total['memory'];
				}

				$groups[$group]['total']['time']   += $total['time'];
				$groups[$group]['total']['memory'] += $total['memory'];
			}

			$count = count($names);

			$groups[$group]['average']['time']   = $groups[$group]['total']['time'] / $count;
			$groups[$group]['average']['memory'] = $groups[$group]['total']['memory'] / $count;
		}

		return $groups;
	}

	/**
	 * 得到所有操作的性能分析 时间 内存
	 *
	 *     list($time, $memory) = Profiler::total($token);
	 *
	 * @param   string  token
	 * @return  array   execution time, memory
	 */
	public static function total($token)
	{
		$mark = Profiler::$_marks[$token];
		if ($mark['stop_time'] === FALSE)
		{
			$mark['stop_time']   = microtime(TRUE);
			$mark['stop_memory'] = memory_get_usage();
		}

		return array
		(
			$mark['stop_time'] - $mark['start_time'],

			$mark['stop_memory'] - $mark['start_memory'],
		);
	}

	/**
	 * Gets the total application run time and memory usage. Caches the result
	 * so that it can be compared between requests.
	 *
	 *     list($time, $memory) = Profiler::application();
	 *
	 * @return  array  execution time, memory
	 * @uses    Core::cache
	 */
	public static function application()
	{
	
			$stats = array(
				'min'   => array(
					'time'   => NULL,
					'memory' => NULL),
				'max'   => array(
					'time'   => NULL,
					'memory' => NULL),
				'total' => array(
					'time'   => NULL,
					'memory' => NULL),
				'count' => 0);
		

		$time = microtime(TRUE) - LXD_START_TIME;

		$memory = memory_get_usage() - LXD_START_MEMORY;

		if ($stats['max']['time'] === NULL OR $time > $stats['max']['time'])
		{
			$stats['max']['time'] = $time;
		}

		if ($stats['min']['time'] === NULL OR $time < $stats['min']['time'])
		{
			$stats['min']['time'] = $time;
		}

		$stats['total']['time'] += $time;

		if ($stats['max']['memory'] === NULL OR $memory > $stats['max']['memory'])
		{
			$stats['max']['memory'] = $memory;
		}

		if ($stats['min']['memory'] === NULL OR $memory < $stats['min']['memory'])
		{
			$stats['min']['memory'] = $memory;
		}

		$stats['total']['memory'] += $memory;

		$stats['count']++;

		$stats['average'] = array(
			'time'   => $stats['total']['time'] / $stats['count'],
			'memory' => $stats['total']['memory'] / $stats['count']);


		$stats['current']['time']   = $time;
		$stats['current']['memory'] = $memory;

		return $stats;
	}

}
